home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / corelib / ncbienv.c < prev    next >
Text File  |  1996-07-05  |  44KB  |  1,469 lines

  1. /*   ncbienv.c
  2. * ===========================================================================
  3. *
  4. *                            PUBLIC DOMAIN NOTICE                          
  5. *               National Center for Biotechnology Information
  6. *                                                                          
  7. *  This software/database is a "United States Government Work" under the   
  8. *  terms of the United States Copyright Act.  It was written as part of    
  9. *  the author's official duties as a United States Government employee and 
  10. *  thus cannot be copyrighted.  This software/database is freely available 
  11. *  to the public for use. The National Library of Medicine and the U.S.    
  12. *  Government have not placed any restriction on its use or reproduction.  
  13. *                                                                          
  14. *  Although all reasonable efforts have been taken to ensure the accuracy  
  15. *  and reliability of the software and data, the NLM and the U.S.          
  16. *  Government do not and cannot warrant the performance or results that    
  17. *  may be obtained by using this software or data. The NLM and the U.S.    
  18. *  Government disclaim all warranties, express or implied, including       
  19. *  warranties of performance, merchantability or fitness for any particular
  20. *  purpose.                                                                
  21. *                                                                          
  22. *  Please cite the author in any work or product based on this material.   
  23. *
  24. * ===========================================================================
  25. *
  26. * File Name:  ncbienv.c
  27. *
  28. * Author:  Ostell
  29. *
  30. * Version Creation Date:   7/7/91
  31. *
  32. * $Revision: 1.6 $
  33. *
  34. * File Description: 
  35. *       portable environment functions, companions for ncbimain.c
  36. *
  37. * Modifications:  
  38. * --------------------------------------------------------------------------
  39. * Date     Name        Description of modification
  40. * -------  ----------  -----------------------------------------------------
  41. * 7/7/91   Kans        Multiple configuration files, get and set functions
  42. * 9-20-91  Schuler     GetAppParam takes default value as an argument
  43. * 1-14-94  Epstein     Merged ncbienv.{unx,vms,dos,msw,mac} into a single file
  44. *
  45. * ==========================================================================
  46. */
  47.  
  48. #include <ncbi.h>
  49. #include <ncbiwin.h>
  50.  
  51. #ifdef OS_UNIX
  52. #include <pwd.h>
  53. #endif /* OS_UNIX */
  54. #ifdef OS_MAC
  55. #include <GestaltEqu.h>
  56. #include <Folders.h>
  57. #include <Strings.h>
  58. #endif /* OS_MAC */
  59. #ifdef OS_VMS
  60. #include <unixlib.h>
  61. #endif /* OS_VMS */
  62.  
  63.  
  64. typedef struct nlm_env_item {
  65.   struct nlm_env_item  PNTR next;
  66.   Nlm_CharPtr          name;
  67.   Nlm_CharPtr          comment;
  68.   Nlm_CharPtr          value;
  69. } Nlm_env_item, PNTR Nlm_env_itemPtr;
  70.  
  71. typedef struct nlm_env_sect {
  72.   struct nlm_env_sect  PNTR next;
  73.   Nlm_CharPtr          name;
  74.   Nlm_CharPtr          comment;
  75.   Nlm_Boolean          transientOnly; /* this field used only by Transient fns */
  76.   struct nlm_env_item  PNTR children;
  77. } Nlm_env_sect, PNTR Nlm_env_sectPtr;
  78.  
  79. typedef struct nlm_env_file {
  80.   struct nlm_env_file  PNTR next;
  81.   Nlm_CharPtr          name;
  82.   Nlm_env_sectPtr      envList;
  83. } Nlm_env_file, PNTR Nlm_env_filePtr;
  84.  
  85.  
  86. Nlm_env_filePtr Nlm_transientFileList = NULL;
  87.  
  88. static Nlm_Boolean Nlm_Qualified PROTO((Nlm_CharPtr path));
  89. static Nlm_Boolean Nlm_TransientLookup PROTO((Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr dflt, Nlm_CharPtr buf, Nlm_Int2 buflen));
  90. static void Nlm_TransientLogSetApp PROTO((Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr value));
  91. static void Nlm_FreeEnvData PROTO((Nlm_env_sectPtr esp));
  92. static void Nlm_FreeTransientData PROTO((void));
  93.  
  94. #ifndef WIN_MSWIN
  95. static FILE *Nlm_OpenConfigFile PROTO((Nlm_CharPtr file, Nlm_Boolean writeMode, Nlm_Boolean create));
  96. static Nlm_CharPtr Nlm_TrimString PROTO((Nlm_CharPtr str));
  97. static Nlm_Boolean Nlm_ReadConfigFile PROTO((FILE *fp));
  98. static Nlm_env_sectPtr Nlm_FindConfigSection PROTO((Nlm_CharPtr section));
  99. static Nlm_env_itemPtr Nlm_FindConfigItem PROTO((Nlm_CharPtr section, Nlm_CharPtr type, Nlm_Boolean create));
  100. static Nlm_Boolean Nlm_WriteConfigFile PROTO((FILE *fp));
  101. static void Nlm_PutComment PROTO((Nlm_CharPtr s, FILE *fp));
  102. static void Nlm_FreeConfigFileData PROTO((void));
  103.  
  104. #ifdef OS_UNIX
  105. static Nlm_CharPtr saveHome = NULL;
  106. #endif /* OS_UNIX */
  107.  
  108. static Nlm_env_sectPtr Nlm_envList = NULL;
  109. static Nlm_CharPtr Nlm_lastParamFile = NULL;
  110. static Nlm_CharPtr Nlm_bottomComment = NULL;
  111.  
  112. /* always FALSE, because this file is trying to emulating MS Windows's  */
  113. /* handling of comments in Param files; however, just change this value */
  114. /* to TRUE to turn this approach around                                 */
  115. static Nlm_Boolean destroyDeadComments = FALSE;
  116.  
  117. /*****************************************************************************
  118. *
  119. * The "guts" of:
  120. *   Nlm_GetAppParam (file, section, type, dflt, buf, buflen)
  121. *      finds parameters from configuration files
  122. *      this version, searching for configuration file(s) in a
  123. *      platform-dependent basis as handled by Nlm_OpenConfigFile()
  124. *
  125. *      if configuration file is found, tries to read the parameter from it.
  126. *
  127. *****************************************************************************/
  128.  
  129. static Nlm_Int2 Nlm_WorkGetAppParam (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr dflt, Nlm_CharPtr buf, Nlm_Int2 buflen, Nlm_Boolean searchTransient)
  130.  
  131. {
  132.   Nlm_env_itemPtr  eip;
  133.   FILE             *fp;
  134.   Nlm_env_sectPtr  esp;
  135.   Nlm_Int2         totlen;
  136.   Nlm_Int2         bytesToAppend;
  137.  
  138.   if (buf != NULL && buflen > 0) {
  139.     *buf = '\0';
  140.     if (searchTransient && Nlm_TransientLookup(file, section, type, dflt, buf, buflen))
  141.     {
  142.       return Nlm_StringLen(buf);
  143.     }
  144.     if (dflt) Nlm_StringNCat (buf, dflt, buflen);
  145.     if (file != NULL && *file != '\0' && section != NULL && *section != '\0') {
  146.       if (Nlm_lastParamFile == NULL ||
  147.           Nlm_StringICmp(Nlm_lastParamFile, file) != 0) {
  148.         Nlm_FreeConfigFileData();
  149.         fp = Nlm_OpenConfigFile (file, FALSE, FALSE);
  150.         if (fp != NULL) {
  151.           Nlm_lastParamFile = Nlm_StringSave(file);
  152.           Nlm_ReadConfigFile (fp);
  153.           Nlm_FileClose (fp);
  154.         }
  155.       }
  156.       if (type != NULL && *type != '\0') {
  157.         eip = Nlm_FindConfigItem (section, type, FALSE);
  158.         if (eip != NULL) {
  159.           *buf = '\0';
  160.           Nlm_StringNCat (buf, eip->value, buflen);
  161.         }
  162.       }
  163.       else { /* return all the types in that section */
  164.         *buf = '\0';
  165.         totlen = 0;
  166.         if ((esp = Nlm_FindConfigSection (section)) != NULL)
  167.         {
  168.           /* traverse the children, allowing the null chars to be inserted */
  169.           /* in between each type-name                                     */
  170.           for (eip = esp->children; eip != NULL; eip = eip->next)
  171.           {
  172.             bytesToAppend = StrLen(eip->name) + 1;
  173.             bytesToAppend = MIN(bytesToAppend, buflen - totlen);
  174.             StrNCpy(&buf[totlen], eip->name, bytesToAppend);
  175.             totlen += bytesToAppend;
  176.           }
  177.           if (totlen > 0 && buf[totlen] == '\0')
  178.             totlen--; /* account for final null character */
  179.         }
  180.         return totlen;
  181.       }
  182.     }
  183.   }
  184.  
  185.   return Nlm_StringLen(buf);
  186. }
  187.  
  188. /*****************************************************************************
  189. *
  190. *   Nlm_SetAppParam (file, section, type, value)
  191. *      finds paths for types of data and fills in path in buf
  192. *      this version
  193. *      1)  looks in the current directory for ".filerc", but will not
  194. *          create a new file in this directory.
  195. *      2)  then looks in the home directory for ".filerc".
  196. *      3)  then looks for an environment variable "NCBI" and takes its
  197. *          value as a complete path to a directory containing the
  198. *          configuration file ".filerc".
  199. *      if configuration file is found, tries to write the parameter to it.
  200. *
  201. *****************************************************************************/
  202.  
  203. Nlm_Boolean LIBCALL Nlm_SetAppParam (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr value)
  204.  
  205. {
  206.   Nlm_env_itemPtr  eip;
  207.   Nlm_env_sectPtr  esp;
  208.   FILE             *fp;
  209.   Nlm_Boolean      rsult;
  210.  
  211.   rsult = FALSE;
  212.   if (file != NULL && *file != '\0' && section != NULL && *section != '\0') {
  213.     Nlm_TransientLogSetApp (file, section, type, value);
  214.     fp = Nlm_OpenConfigFile (file, FALSE, TRUE);
  215.     if (fp != NULL) {
  216.       if (Nlm_lastParamFile == NULL ||
  217.           Nlm_StringICmp(Nlm_lastParamFile, file) != 0) {
  218.         Nlm_FreeConfigFileData();
  219.         Nlm_lastParamFile = Nlm_StringSave(file);
  220.         Nlm_ReadConfigFile (fp);
  221.       }
  222.       Nlm_FileClose (fp);
  223.       if (type != NULL && *type != '\0')
  224.       {
  225.         eip = Nlm_FindConfigItem (section, type, TRUE);
  226.         if (eip != NULL) {
  227.           if (eip->value != NULL) {
  228.             eip->value = (Nlm_CharPtr) Nlm_MemFree (eip->value);
  229.           }
  230. #ifdef DCLAP
  231.               /* dgg - this is according to MS spec, and need this */
  232.           if (value == NULL)  
  233.                   eip->name = (Nlm_CharPtr) Nlm_MemFree(eip->name);
  234.           else
  235. #endif
  236.           eip->value = Nlm_StringSave (value);
  237.           rsult = TRUE;
  238.         }
  239.       }
  240.       else { /* wipe out that section */
  241.         esp = Nlm_FindConfigSection (section);
  242.         if (esp != NULL) { /* kill section by deleting name (leave comments)*/
  243.           esp->name = (Nlm_CharPtr) Nlm_MemFree(esp->name);
  244.           rsult = TRUE;
  245.         }
  246.       }
  247.           
  248.       fp = Nlm_OpenConfigFile (file, TRUE, FALSE);
  249.       if (fp != NULL) {
  250.         Nlm_WriteConfigFile (fp);
  251.         Nlm_FileClose (fp);
  252.       }
  253.     }
  254.   }
  255.  
  256.   return rsult;
  257. }
  258.  
  259. #ifdef OS_UNIX
  260. /*****************************************************************************
  261. *
  262. *   Nlm_GetHome (buf, buflen)
  263. *      returns the path of the home directory
  264. *
  265. *****************************************************************************/
  266.  
  267. #ifndef L_cuserid
  268. #define L_cuserid 9
  269. #endif
  270.  
  271. static Nlm_Boolean Nlm_GetHome PROTO((Nlm_CharPtr buf, Nlm_Int2 buflen));
  272. static Nlm_Boolean Nlm_GetHome (Nlm_CharPtr buf, Nlm_Int2 buflen)
  273.  
  274. {
  275.   char           *getlogin PROTO((void));
  276. /*
  277. #ifndef COMP_ACC
  278.   struct passwd  *getpwuid PROTO((uid_t uid));
  279. #endif
  280. */
  281.  
  282.   Nlm_CharPtr    cp;
  283.   Nlm_Boolean    found;
  284.   struct passwd  *pswd;
  285.   Nlm_Char       whoiam [L_cuserid + 1];
  286.  
  287.   if (saveHome != NULL)
  288.   { /* return cached value, if available */
  289.       Nlm_StringNCpy (buf, saveHome, buflen);
  290.       return TRUE;
  291.   }
  292.  
  293.   whoiam [0] = '\0';
  294.   found = FALSE;
  295.   cp = getlogin ();
  296.   if (cp != NULL && cp [0] != '\0') {
  297.     Nlm_StringNCpy (whoiam, cp, sizeof (whoiam) - 1);
  298.     whoiam [sizeof (whoiam) - 1] = '\0';
  299.     found = TRUE;
  300.   } else {
  301.     setpwent ();
  302.     pswd = getpwuid (getuid ());
  303.     if (pswd != NULL) {
  304.       Nlm_StringNCpy (whoiam, pswd->pw_name, sizeof (whoiam) - 1);
  305.       whoiam [sizeof (whoiam) - 1] = '\0';
  306.       found = TRUE;
  307.     }
  308.   }
  309.   if (found) {
  310.     setpwent ();
  311.     pswd = getpwnam (whoiam);
  312.     if (pswd != NULL) {
  313.         Nlm_StringNCpy (buf, pswd->pw_dir, buflen);
  314.         if (saveHome == NULL)
  315.         {
  316.             saveHome = Nlm_StringSave(pswd->pw_dir);
  317.         }
  318.     } else {
  319.       found = FALSE;
  320.     }
  321.   }
  322.   return found;
  323. }
  324.  
  325. /*****************************************************************************
  326. *
  327. *   Nlm_OpenConfigFile (file, writeMode, create)
  328. *      returns a file pointer to the specified configuration file.
  329. *      1)  looks in the current directory for ".filerc", but will not
  330. *          create a new file in this directory.
  331. *      2)  then looks in the home directory for ".filerc".
  332. *      3)  then looks for an environment variable "NCBI" and takes its
  333. *          value as a complete path to a directory containing the
  334. *          configuration file "filerc" or ".filerc".
  335. *
  336. *****************************************************************************/
  337.  
  338. static FILE *Nlm_OpenConfigFile (Nlm_CharPtr file, Nlm_Boolean writeMode, Nlm_Boolean create)
  339.  
  340. {
  341.   FILE      *fp;
  342.   Nlm_Int2  i;
  343.   Nlm_Int2  len;
  344.   FILE      *newfp;
  345.   Nlm_Char  path [PATH_MAX+1];
  346.   char      *pth;
  347.   Nlm_Char  str [FILENAME_MAX+1];
  348.  
  349.   fp = NULL;
  350.   if (file != NULL) {
  351.     newfp = NULL;
  352.     Nlm_StringMove (str, ".");
  353.     Nlm_StringNCat (str, file, sizeof (str) - 3);
  354.     if ( ! Nlm_Qualified (str))
  355.     { /* use the user's extension instead of the "rc" extension */
  356.       Nlm_StringCat (str, "rc");
  357.     }
  358.     len = (Nlm_Int2) Nlm_StringLen (str);
  359.     for (i = 0; i < len; i++) {
  360.       str [i] = TO_LOWER (str [i]);
  361.     }
  362.     path[0] = '\0';
  363.     Nlm_StringCpy (path, str);
  364.     fp = Nlm_FileOpen (path, "r");
  365.     if (fp == NULL) {
  366.       path[0] = '\0';
  367.       if (Nlm_GetHome (path, sizeof (path))) {
  368.         Nlm_FileBuildPath(path, NULL, str);
  369.       } else {
  370.         Nlm_StringCpy (path, str);
  371.       }
  372.       fp = Nlm_FileOpen (path, "r");
  373.       if (fp == NULL && create) {
  374.         newfp = Nlm_FileOpen (path, "w");
  375.         Nlm_FileClose (newfp);
  376.         newfp = Nlm_FileOpen (path, "r");
  377.       }
  378.     }
  379.     if (fp == NULL) {
  380.       path[0] = '\0';
  381.       pth = getenv ("NCBI");
  382.       if (pth != NULL) {
  383.         Nlm_FileBuildPath(path, pth, str + 1);
  384.         fp = Nlm_FileOpen (path, "r");
  385.         if (fp == NULL) {
  386.           path[0] = '\0';
  387.           Nlm_FileBuildPath(path, pth, str);
  388.           fp = Nlm_FileOpen (path, "r");
  389.         }
  390.       }
  391.     }
  392.     if (newfp != NULL) {
  393.       if (fp != NULL) {
  394.         Nlm_FileClose (newfp);
  395.         newfp = NULL;
  396.       } else {
  397.         fp = newfp;
  398.       }
  399.     }
  400.     if (writeMode && fp != NULL) {
  401.       Nlm_FileClose (fp);
  402.       fp = Nlm_FileOpen (path, "w");
  403.     }
  404.   }
  405.   return fp;
  406. }
  407.  
  408. #endif /* OS_UNIX */
  409.  
  410.  
  411. #ifdef OS_MAC
  412. /*****************************************************************************
  413. *
  414. *   Nlm_OpenConfigFile (file, writeMode, create)
  415. *      returns a file pointer to the specified configuration file.
  416. *      1)  looks in the System Folder for "file.cnf"
  417. *      2)  then looks in System Folder:Preferences for "file.cnf"
  418. *
  419. *****************************************************************************/
  420.  
  421. static FILE *Nlm_OpenConfigFile (Nlm_CharPtr file, Nlm_Boolean writeMode, Nlm_Boolean create)
  422.  
  423. {
  424.   WDPBRec      block;
  425.   Nlm_Char     directory [PATH_MAX];
  426.   long         dirID;
  427.   OSErr        err;
  428.   OSType       fCreator;
  429.   Nlm_Int2     fError;
  430.   FILE         *fp;
  431.   FInfo        finfo;
  432.   OSType       fType;
  433.   long         gesResponse;
  434.   Nlm_Int2     i;
  435.   Nlm_Int2     len;
  436.   CInfoPBRec   params;
  437.   Nlm_Char     str [FILENAME_MAX+1];
  438.   SysEnvRec    sysenv;
  439.   Nlm_Char     temp [PATH_MAX];
  440.   Nlm_CharPtr  tmp;
  441.   short        vRefNum;
  442.  
  443.   fp = NULL;
  444.   if (file != NULL) {
  445.     Nlm_StringNCpy (str, file, sizeof (str) - 4);
  446.     if ( ! Nlm_Qualified (str) ) {
  447.       Nlm_StringCat (str, ".cnf");
  448.     }
  449.     len = (Nlm_Int2) Nlm_StringLen (str);
  450.     for (i = 0; i < len; i++) {
  451.       str [i] = TO_LOWER (str [i]);
  452.     }
  453.     if (SysEnvirons (curSysEnvVers, &sysenv) == noErr) {
  454.       block.ioNamePtr = NULL;
  455.       block.ioVRefNum = sysenv.sysVRefNum;
  456.       block.ioWDIndex = 0;
  457.       block.ioWDProcID = 0;
  458.       PBGetWDInfo (&block, FALSE);
  459.       dirID = block.ioWDDirID;
  460.       vRefNum = block.ioWDVRefNum;
  461.       temp [0] = '\0';
  462.       params.dirInfo.ioNamePtr = (StringPtr) directory;
  463.       params.dirInfo.ioDrParID = dirID;
  464.       do {
  465.         params.dirInfo.ioVRefNum = vRefNum;
  466.         params.dirInfo.ioFDirIndex = -1;
  467.         params.dirInfo.ioDrDirID = params.dirInfo.ioDrParID;
  468.         err = PBGetCatInfo (¶ms, FALSE);
  469. #if defined(COMP_MPW) || defined(COMP_CODEWAR)
  470.   p2cstr ((StringPtr) directory);
  471. #else
  472. #ifdef COMP_THINKC
  473.   PtoCstr ((StringPtr) directory);
  474. #endif
  475. #endif
  476.         Nlm_StringCat (directory, DIRDELIMSTR);
  477.         Nlm_StringCat (directory, temp);
  478.         Nlm_StringCpy (temp, directory);
  479.       } while (params.dirInfo.ioDrDirID != fsRtDirID);
  480.       tmp = Nlm_StringMove (directory, temp);
  481.       tmp = Nlm_StringMove (tmp, str);
  482.       fp = Nlm_FileOpen (directory, "r");
  483.       if (fp == NULL) {
  484.         if (! Gestalt (gestaltFindFolderAttr, &gesResponse) &&
  485.             (gesResponse & (1 << gestaltFindFolderPresent))) {
  486.           err = FindFolder(kOnSystemDisk, kPreferencesFolderType,
  487.                            kCreateFolder, &vRefNum, &dirID);
  488.           if (err == noErr) {
  489.             params.dirInfo.ioNamePtr = (StringPtr) directory;
  490.             params.dirInfo.ioDrDirID = dirID;
  491.             params.dirInfo.ioVRefNum = vRefNum;
  492.             params.dirInfo.ioFDirIndex = -1;
  493.             err = PBGetCatInfo (¶ms, FALSE);
  494. #if defined(COMP_MPW) || defined(COMP_CODEWAR)
  495.   p2cstr ((StringPtr) directory);
  496. #else
  497. #ifdef COMP_THINKC
  498.   PtoCstr ((StringPtr) directory);
  499. #endif
  500. #endif
  501.             Nlm_StringCat (temp, directory);
  502.             Nlm_StringCat (temp, DIRDELIMSTR);
  503.             tmp = Nlm_StringMove (directory, temp);
  504.             tmp = Nlm_StringMove (tmp, str);
  505.           } else {
  506.             tmp = Nlm_StringMove (directory, temp);
  507.             tmp = Nlm_StringMove (tmp, "Preferences");
  508.             tmp = Nlm_StringMove (tmp, DIRDELIMSTR);
  509.             tmp = Nlm_StringMove (tmp, str);
  510.           }
  511.         } else {
  512.           tmp = Nlm_StringMove (directory, temp);
  513.           tmp = Nlm_StringMove (tmp, "Preferences");
  514.           tmp = Nlm_StringMove (tmp, DIRDELIMSTR);
  515.           tmp = Nlm_StringMove (tmp, str);
  516.         }
  517.         fp = Nlm_FileOpen (directory, "r");
  518.       }
  519.       if (fp == NULL && create) {
  520.         tmp = Nlm_StringMove (directory, temp);
  521.         tmp = Nlm_StringMove (tmp, str);
  522.         fp = Nlm_FileOpen (directory, "w");
  523.         Nlm_StringCpy (temp, directory);
  524. #if defined(COMP_MPW) || defined(COMP_CODEWAR)
  525.     c2pstr ((char *) temp);
  526. #else
  527. #ifdef COMP_THINKC
  528.     CtoPstr ((char *) temp);
  529. #endif
  530. #endif
  531.         fError = GetFInfo ((StringPtr) temp, 0, &finfo);
  532.         if (fError == 0) {
  533.           finfo.fdCreator = 'ttxt';
  534.           finfo.fdType = 'TEXT';
  535.           fError = SetFInfo ((StringPtr) temp, 0, &finfo);
  536.         }
  537.         Nlm_FileClose (fp);
  538.         fp = Nlm_FileOpen (directory, "r");
  539.       }
  540.       Nlm_StringCpy (temp, directory);
  541.       if (writeMode && fp != NULL) {
  542.         Nlm_FileClose (fp);
  543. #if defined(COMP_MPW) || defined(COMP_CODEWAR)
  544.     c2pstr ((char *) temp);
  545. #else
  546. #ifdef COMP_THINKC
  547.     CtoPstr ((char *) temp);
  548. #endif
  549. #endif
  550.         fType = 'TEXT';
  551.         fCreator = '    ';
  552.         fError = GetFInfo ((StringPtr) temp, 0, &finfo);
  553.         if (fError == 0) {
  554.           fCreator = finfo.fdCreator;
  555.           fType = finfo.fdType;
  556.         }
  557.         fp = Nlm_FileOpen (directory, "w");
  558.         fError = GetFInfo ((StringPtr) temp, 0, &finfo);
  559.         if (fError == 0) {
  560.           finfo.fdCreator = fCreator;
  561.           finfo.fdType = fType;
  562.           fError = SetFInfo ((StringPtr) temp, 0, &finfo);
  563.         }
  564.       }
  565.     }
  566.   }
  567.   return fp;
  568. }
  569. #endif /* OS_MAC */
  570.  
  571. #ifdef OS_VMS
  572. /*****************************************************************************
  573. *
  574. *   Nlm_GetHome (buf, buflen)
  575. *      returns the path of the home directory
  576. *
  577. *****************************************************************************/
  578.  
  579. static Nlm_Boolean Nlm_GetHome PROTO((Nlm_CharPtr buf, Nlm_Int2 buflen));
  580. static Nlm_Boolean Nlm_GetHome (Nlm_CharPtr buf, Nlm_Int2 buflen)
  581.  
  582. {
  583.   StringCpy(buf, getenv("SYS$LOGIN"));
  584.   return TRUE;
  585. }
  586.  
  587. /*****************************************************************************
  588. *
  589. *   Nlm_OpenConfigFile (file, writeMode, create)
  590. *      returns a file pointer to the specified configuration file.
  591. *      1)  looks in the current directory for "file.cfg", but will not
  592. *          create a new file in this directory.
  593. *      2)  then looks in the home directory for "file.cfg".
  594. *      3)  then looks for an environment variable "NCBI" and takes its
  595. *          value as a complete path to a directory containing the
  596. *          configuration file "file.cfg".
  597. *
  598. *****************************************************************************/
  599.  
  600. static FILE *Nlm_OpenConfigFile (Nlm_CharPtr file, Nlm_Boolean writeMode, Nlm_Boolean create)
  601.  
  602. {
  603.   FILE      *fp;
  604.   Nlm_Int2  i;
  605.   Nlm_Int2  len;
  606.   FILE      *newfp;
  607.   Nlm_Char  path [PATH_MAX+1];
  608.   char      *pth;
  609.   Nlm_Char  str [FILENAME_MAX+1];
  610.  
  611.   fp = NULL;
  612.  
  613.   if (file != NULL) {
  614.     newfp = NULL;
  615.     Nlm_StringNCpy (str, file, sizeof (str) - 3);
  616.     if ( ! Nlm_Qualified (str) ) {
  617.       Nlm_StringCat (str, ".cfg");
  618.     }
  619.     len = (Nlm_Int2) Nlm_StringLen (str);
  620.     for (i = 0; i < len; i++) {
  621.       str [i] = TO_LOWER (str [i]);
  622.     }
  623.     path[0] = '\0';
  624.     Nlm_StringCpy (path, str);
  625.  
  626.     fp = Nlm_FileOpen (path, "r");  /* File exists? */
  627.     if (fp == NULL) {
  628.       path[0] = '\0';
  629.       if (Nlm_GetHome (path, sizeof (path))) {
  630.         Nlm_FileBuildPath(path, NULL, str);
  631.       } else {
  632.         Nlm_StringCpy (path, str);
  633.       }
  634.       fp = Nlm_FileOpen (path, "r");   /* File exists? */
  635.       if (fp == NULL && create) {
  636.         newfp = Nlm_FileOpen (path, "w");
  637.         Nlm_FileClose (newfp);
  638.         newfp = Nlm_FileOpen (path, "r");
  639.       }
  640.     }
  641.  
  642.     if (fp == NULL) {
  643.       path[0] = '\0';
  644.       pth = getenv ("NCBI");
  645.       if (pth != NULL) {
  646.         Nlm_FileBuildPath(path, pth, str);
  647.         fp = Nlm_FileOpen (path, "r");
  648.       }
  649.     }
  650.  
  651.     if (newfp != NULL) {
  652.       if (fp != NULL) {
  653.         Nlm_FileClose (newfp);
  654.         newfp = NULL;
  655.       } else {
  656.         fp = newfp;
  657.       }
  658.     }
  659.  
  660.     /*
  661.     ** On VMS if a file is opened for write a new version is created.
  662.     ** This section of code check for "writeMode" and an existing file
  663.     ** if both are true.  Get the currently open file's name and delete
  664.     ** it.  Open a new one in write mode.
  665.     **
  666.     ** Side effects: This will replace the highest existing file version,
  667.     ** but not older version.  There exists the possibility that a user's
  668.     ** custom change may get lost.  A possible workaround for this would
  669.     ** be to have the calling program make a new copy (one higher version)
  670.     ** of the existing file before doing extensive write to the params
  671.     ** file OR keep a static flag in this routine which does  delete the
  672.     ** first time time.
  673.     */
  674.  
  675.     if (writeMode && fp != NULL) {
  676.       char temp[256];
  677.       fgetname(fp,temp);
  678.       Nlm_FileClose (fp);
  679.       delete(temp);
  680.       fp = Nlm_FileOpen (path, "w");
  681.     }
  682.   }
  683.   return fp;
  684. }
  685.  
  686. #endif /* OS_VMS */
  687.  
  688. #ifdef OS_DOS
  689. /*****************************************************************************
  690. *
  691. *   Nlm_OpenConfigFile (file, writeMode, create)
  692. *      returns a file pointer to the specified configuration file.
  693. *      1)  looks in the current directory for "file.cfg"
  694. *      2)  then looks for an environment variable "NCBI" and takes its
  695. *           value as a complete path to a directory containing the
  696. *           configuration file "file.cfg".
  697. *
  698. *****************************************************************************/
  699.  
  700. static FILE *Nlm_OpenConfigFile (Nlm_CharPtr file, Nlm_Boolean writeMode, Nlm_Boolean create)
  701.  
  702. {
  703.   FILE      *fp;
  704.   Nlm_Int2  i;
  705.   Nlm_Int2  len;
  706.   Nlm_Char  path [PATH_MAX+1];
  707.   char      *pth;
  708.   Nlm_Char  str [FILENAME_MAX+1];
  709.  
  710.   fp = NULL;
  711.   if (file != NULL) {
  712.     Nlm_StringNCpy (str, file, sizeof (str) - 4);
  713.     if ( ! Nlm_Qualified (str) ) {
  714.       Nlm_StringCat (str, ".cfg");
  715.     }
  716.     len = (Nlm_Int2) Nlm_StringLen (str);
  717.     for (i = 0; i < len; i++) {
  718.       str [i] = TO_LOWER (str [i]);
  719.     }
  720.     path[0] = '\0';
  721.     Nlm_StringCpy (path, str);
  722.     fp = Nlm_FileOpen (path, "r");
  723.     if (fp == NULL) {
  724.       pth = getenv ("NCBI");
  725.       if (pth != NULL) {
  726.         path[0] = '\0';
  727.         Nlm_FileBuildPath (path, pth, str);
  728.         fp = Nlm_FileOpen (path, "r");
  729.         if (fp == NULL && create) {
  730.           fp = Nlm_FileOpen (path, "w");
  731.           Nlm_FileClose (fp);
  732.           fp = Nlm_FileOpen (path, "r");
  733.         }
  734.       } else if (create) {
  735.         fp = Nlm_FileOpen (path, "w");
  736.         Nlm_FileClose (fp);
  737.         fp = Nlm_FileOpen (path, "r");
  738.       } else {
  739.         path[0] = '\0';
  740.       }
  741.     }
  742.     if (writeMode && fp != NULL) {
  743.       Nlm_FileClose (fp);
  744.       fp = Nlm_FileOpen (path, "w");
  745.     }
  746.   }
  747.   return fp;
  748. }
  749. #endif /* OS_DOS */
  750.  
  751. /*****************************************************************************
  752. *
  753. *   Nlm_TrimString (str)
  754. *      strips trailing spaces, \r, \n
  755. *
  756. *****************************************************************************/
  757.  
  758. static Nlm_CharPtr Nlm_TrimString (Nlm_CharPtr str)
  759.  
  760. {
  761.   Nlm_Char     ch;
  762.   Nlm_CharPtr  spc;
  763.   Nlm_CharPtr  tmp;
  764.  
  765.   if (str != NULL) {
  766.     ch = *str;
  767.     while (ch == ' ' || ch == '\t') {
  768.       str++;
  769.       ch = *str;
  770.     }
  771.     tmp = str;
  772.     spc = NULL;
  773.     ch = *tmp;
  774.     while (ch != '\0' && ch != '\r' && ch != '\n') {
  775.       if (ch == ' ' || ch == '\t') {
  776.         if (spc == NULL) {
  777.           spc = tmp;
  778.         }
  779.       } else {
  780.         spc = NULL;
  781.       }
  782.       tmp++;
  783.       ch = *tmp;
  784.     }
  785.     *tmp = '\0';
  786.     if (spc != NULL) {
  787.       *spc = '\0';
  788.     }
  789.   }
  790.   return str;
  791. }
  792.  
  793. /*****************************************************************************
  794. *
  795. *   Nlm_ReadConfigFile (fp)
  796. *      reads parameters from configuration file to memory structure
  797. *
  798. *****************************************************************************/
  799.  
  800. static Nlm_Boolean Nlm_ReadConfigFile (FILE *fp)
  801.  
  802. {
  803.   Nlm_Char         ch;
  804.   Nlm_env_itemPtr  eip;
  805.   Nlm_env_sectPtr  esp;
  806.   Nlm_env_itemPtr  lastEip;
  807.   Nlm_env_sectPtr  lastEsp;
  808.   Nlm_CharPtr      mid;
  809.   Nlm_Char         str [256];
  810.   Nlm_CharPtr      tmp;
  811.   Nlm_CharPtr      comment;
  812.  
  813.   if (fp != NULL) {
  814.     Nlm_envList = NULL;
  815.     esp = NULL;
  816.     lastEsp = NULL;
  817.     eip = NULL;
  818.     lastEip = NULL;
  819.     comment = NULL;
  820.     while (fgets (str, sizeof (str), fp)) {
  821.       ch = *str;
  822.       if (ch != '\n' && ch != '\r') {
  823.         if (ch == ';') { /* comment */
  824.           if (comment == NULL) { /* first comment */
  825.              comment = Nlm_StringSave(str);
  826.           }
  827.           else { /* append to existing comment */
  828.              tmp = (Nlm_CharPtr) Nlm_MemNew(StrLen(comment) + StrLen(str) + 1);
  829.              StrCpy(tmp, comment);
  830.              StrCat(tmp, str);
  831.              comment = (Nlm_CharPtr) Nlm_MemFree(comment);
  832.              comment = tmp;
  833.           }
  834.         } else if (ch == '[') {
  835.           if (esp == NULL) {
  836.             esp = (Nlm_env_sectPtr) Nlm_MemNew (sizeof (Nlm_env_sect));
  837.             lastEsp = esp;
  838.             Nlm_envList = esp;
  839.           } else {
  840.             esp = (Nlm_env_sectPtr) Nlm_MemNew (sizeof (Nlm_env_sect));
  841.             lastEsp->next = esp;
  842.             lastEsp = esp;
  843.           }
  844.           esp->comment = comment;
  845.           comment = NULL;
  846.           tmp = str;
  847.           ch = *tmp;
  848.           while (ch != '\0' && ch != ']') {
  849.             tmp++;
  850.             ch = *tmp;
  851.           }
  852.           *tmp = '\0';
  853.           esp->name = Nlm_StringSave (str + 1);
  854.           eip = NULL;
  855.           lastEip = NULL;
  856.         } else if (esp != NULL) {
  857.           if (eip == NULL) {
  858.             eip = (Nlm_env_itemPtr) Nlm_MemNew (sizeof (Nlm_env_item));
  859.             lastEip = eip;
  860.             esp->children = eip;
  861.           } else {
  862.             eip = (Nlm_env_itemPtr) Nlm_MemNew (sizeof (Nlm_env_item));
  863.             lastEip->next = eip;
  864.             lastEip = eip;
  865.           }
  866.           eip->comment = comment;
  867.           comment = NULL;
  868.           tmp = str;
  869.           mid = str;
  870.           ch = *tmp;
  871.           while (ch != '\0' && ch != '\n') {
  872.             if (ch == '=' && mid == str) {
  873.               mid = tmp;
  874.               *mid++ = '\0';
  875.             }
  876.             tmp++;
  877.             ch = *tmp;
  878.           }
  879.           *tmp = '\0';
  880.           eip->name = Nlm_StringSave (Nlm_TrimString (str));
  881.           eip->value = Nlm_StringSave (Nlm_TrimString (mid));
  882.         }
  883.       }
  884.     }
  885.  
  886.     /* any comments which appeared after the final key of the final section */
  887.     Nlm_bottomComment = comment;
  888.   }
  889.   return TRUE;
  890. }
  891.  
  892. static Nlm_env_sectPtr Nlm_FindConfigSection (Nlm_CharPtr section)
  893. {
  894.   Nlm_env_sectPtr esp;
  895.  
  896.   if (section == NULL)
  897.     return NULL;
  898.  
  899.   for (esp = Nlm_envList; esp != NULL; esp = esp->next)
  900.   {
  901.     if (esp->name != NULL && Nlm_StringICmp(section, esp->name) == 0)
  902.        return esp;
  903.   }
  904.  
  905.   return NULL;
  906. }
  907.  
  908. /*****************************************************************************
  909. *
  910. *   Nlm_FindConfigItem (section, type, create)
  911. *      finds parameter in memory structure
  912. *
  913. *****************************************************************************/
  914.  
  915. static Nlm_env_itemPtr Nlm_FindConfigItem (Nlm_CharPtr section, Nlm_CharPtr type, Nlm_Boolean create)
  916.  
  917. {
  918.   Nlm_env_itemPtr  eip;
  919.   Nlm_env_sectPtr  esp;
  920.   Nlm_Boolean      goOn;
  921.   Nlm_env_itemPtr  lastEip;
  922.   Nlm_env_sectPtr  lastEsp;
  923.  
  924.   eip = NULL;
  925.   if (section != NULL && type != NULL) {
  926.     goOn = TRUE;
  927.     esp = Nlm_envList;
  928.     lastEsp = esp;
  929.     while (esp != NULL && goOn) {
  930.       if (esp->name != NULL && Nlm_StringICmp (section, esp->name) == 0) {
  931.         goOn = FALSE;
  932.       } else {
  933.         lastEsp = esp;
  934.         esp = esp->next;
  935.       }
  936.     }
  937.     if (goOn && create) {
  938.       if (Nlm_envList != NULL) {
  939.         esp = (Nlm_env_sectPtr) Nlm_MemNew (sizeof (Nlm_env_sect));
  940.         if (esp != NULL) {
  941.           esp->name = Nlm_StringSave (section);
  942.           lastEsp->next = esp;
  943.         }
  944.       } else {
  945.         esp = (Nlm_env_sectPtr) Nlm_MemNew (sizeof (Nlm_env_sect));
  946.         if (esp != NULL) {
  947.           esp->name = Nlm_StringSave (section);
  948.         }
  949.         Nlm_envList = esp;
  950.       }
  951.     }
  952.     if (esp != NULL) {
  953.       eip = esp->children;
  954.       if (eip != NULL) {
  955.         goOn = TRUE;
  956.         lastEip = eip;
  957.         while (eip != NULL && goOn) {
  958.           if (eip->name != NULL && Nlm_StringICmp (type, eip->name) == 0) {
  959.             goOn = FALSE;
  960.           } else {
  961.             lastEip = eip;
  962.             eip = eip->next;
  963.           }
  964.         }
  965.         if (goOn && create) {
  966.           eip = (Nlm_env_itemPtr) Nlm_MemNew (sizeof (Nlm_env_item));
  967.           if (eip != NULL) {
  968.             eip->name = Nlm_StringSave (type);
  969.             lastEip->next = eip;
  970.           }
  971.         }
  972.       } else if (create) {
  973.         eip = (Nlm_env_itemPtr) Nlm_MemNew (sizeof (Nlm_env_item));
  974.         if (eip != NULL) {
  975.           eip->name = Nlm_StringSave (type);
  976.           esp->children = eip;
  977.         }
  978.       }
  979.     }
  980.   }
  981.   return eip;
  982. }
  983.  
  984. /*****************************************************************************
  985. *
  986. *   Nlm_WriteConfigFile (fp)
  987. *      writes parameters to configuration file from memory structure
  988. *
  989. *****************************************************************************/
  990.  
  991. static Nlm_Boolean Nlm_WriteConfigFile (FILE *fp)
  992.  
  993. {
  994.   Nlm_env_itemPtr  eip;
  995.   Nlm_env_sectPtr  esp;
  996.  
  997.   if (Nlm_envList != NULL && fp != NULL) {
  998.     esp = Nlm_envList;
  999.     while (esp != NULL) {
  1000.       if (! destroyDeadComments || esp->name != NULL)
  1001.       {
  1002.         Nlm_PutComment (esp->comment, fp);
  1003.       }
  1004.       if (esp->name != NULL)
  1005.       {
  1006.         fputc ('[', fp);
  1007.         fputs (esp->name, fp);
  1008.         fputs ("]\n", fp);
  1009.       }
  1010.       eip = esp->children;
  1011.       while (eip != NULL) {
  1012.         if (! destroyDeadComments)
  1013.         {
  1014.           Nlm_PutComment (eip->comment, fp);
  1015.         }
  1016.         if (esp->name != NULL && eip->name != NULL && eip->value != NULL) {
  1017.           if (destroyDeadComments)
  1018.           {
  1019.             Nlm_PutComment (eip->comment, fp);
  1020.           }
  1021.           fputs (eip->name, fp);
  1022.           fputc ('=', fp);
  1023.           fputs (eip->value, fp);
  1024.           fputc ('\n', fp);
  1025.         }
  1026.         eip = eip->next;
  1027.       }
  1028.       if (esp->name != NULL)
  1029.       {
  1030.         fputc ('\n', fp);
  1031.       }
  1032.       esp = esp->next;
  1033.     }
  1034.   }
  1035.  
  1036.   if (fp != NULL)
  1037.     Nlm_PutComment(Nlm_bottomComment, fp);
  1038.  
  1039.   return TRUE;
  1040. }
  1041.  
  1042. /*****************************************************************************
  1043. *
  1044. *   Nlm_FreeConfigFileData ()
  1045. *      frees parameter structure in memory
  1046. *
  1047. *****************************************************************************/
  1048.  
  1049. static void Nlm_FreeConfigFileData (void)
  1050.  
  1051. {
  1052.   Nlm_bottomComment = (Nlm_CharPtr) Nlm_MemFree(Nlm_bottomComment);
  1053.   if (Nlm_lastParamFile != NULL)
  1054.     Nlm_lastParamFile = (Nlm_CharPtr) Nlm_MemFree(Nlm_lastParamFile);
  1055.  
  1056.   if (Nlm_envList != NULL) {
  1057.     Nlm_FreeEnvData (Nlm_envList);
  1058.     Nlm_envList = NULL;
  1059.   }
  1060. }
  1061.  
  1062.  
  1063. /*****************************************************************************
  1064. *
  1065. *   Nlm_FreeConfigStruct ()
  1066. *      frees parameter structure in memory, and perform other cleanup
  1067. *
  1068. *****************************************************************************/
  1069.  
  1070. void LIBCALL Nlm_FreeConfigStruct (void)
  1071.  
  1072. {
  1073.   Nlm_FreeConfigFileData ();
  1074.   Nlm_FreeTransientData ();
  1075. #ifdef OS_UNIX
  1076.   if (saveHome != NULL)
  1077.   {
  1078.       saveHome = (Nlm_CharPtr) Nlm_MemFree(saveHome);
  1079.   }
  1080. #endif /* OS_UNIX */
  1081. }
  1082.  
  1083.  
  1084. /*****************************************************************************
  1085. *
  1086. *   Nlm_PutComment()
  1087. *      output a comment to the config file
  1088. *
  1089. *****************************************************************************/
  1090.  
  1091. static void Nlm_PutComment (Nlm_CharPtr s, FILE *fp)
  1092.  
  1093. {
  1094.   if (s != NULL)
  1095.     fputs(s, fp);
  1096. }
  1097.  
  1098. #else /* MS-WIN */
  1099. /*****************************************************************************
  1100. *
  1101. * The "guts" of:
  1102. *   Nlm_GetAppParam (file, section, type, buf, buflen)
  1103. *      finds parameters from configuration files
  1104. *      if configuration file is found, trys to read the parameter from it.
  1105. *
  1106. *****************************************************************************/
  1107.  
  1108. static Nlm_Int2 Nlm_WorkGetAppParam (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr dflt, Nlm_CharPtr buf, Nlm_Int2 buflen, Nlm_Boolean searchTransient)
  1109.  
  1110. {
  1111.   Nlm_Char     path [PATH_MAX+1];
  1112. #ifdef DCLAP
  1113.     Nlm_Int4     totlen;
  1114. #endif
  1115.  
  1116.   if (buf != NULL && buflen > 0) {
  1117.     *buf = '\0';
  1118.     if (searchTransient && Nlm_TransientLookup(file, section, type, dflt, buf, buflen))
  1119.     {
  1120.       return Nlm_StringLen(buf);
  1121.     }
  1122.     if (dflt) Nlm_StringNCat (buf, dflt, buflen);
  1123.     if (file != NULL && *file != '\0' && section != NULL && *section != '\0') {
  1124.       Nlm_StringNCpy (path, file, sizeof (path) - 4);
  1125.       if ( ! Nlm_Qualified (path) ) {
  1126.         Nlm_StringCat (path, ".INI");
  1127.       }
  1128. #ifdef DCLAP
  1129.             totlen=
  1130. #endif
  1131.       GetPrivateProfileString (section, type, dflt, buf, buflen, path);
  1132.     }
  1133.   }
  1134. #ifdef DCLAP
  1135. /* we want same result here as above for type==NULL */
  1136.  if (type==NULL) return totlen;
  1137.  else
  1138. #endif
  1139.   return Nlm_StringLen (buf);
  1140. }
  1141.  
  1142. /*****************************************************************************
  1143. *
  1144. *   Nlm_SetAppParam (file, section, type, value)
  1145. *      finds paths for types of data and fills in path in buf
  1146. *      if configuration file is found, trys to write the parameter to it.
  1147. *
  1148. *****************************************************************************/
  1149.  
  1150. Nlm_Boolean LIBCALL  Nlm_SetAppParam (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr value)    /* value */
  1151.  
  1152. {
  1153.   Nlm_Char     path [PATH_MAX+1];
  1154.   Nlm_Boolean  rsult;
  1155.  
  1156.   rsult = FALSE;
  1157.   if (file != NULL && *file != '\0' && section != NULL && *section != '\0') {
  1158.     Nlm_StringNCpy (path, file, sizeof (path) - 4);
  1159.     if ( ! Nlm_Qualified (path) ) {
  1160.       Nlm_StringCat (path, ".INI");
  1161.     }
  1162.     Nlm_TransientLogSetApp (file, section, type, value);
  1163.     if (WritePrivateProfileString (section, type, value, path)) {
  1164.       rsult = TRUE;
  1165.     }
  1166.   }
  1167.   return rsult;
  1168. }
  1169.  
  1170. /*****************************************************************************
  1171. *
  1172. *   Nlm_FreeConfigStruct ()
  1173. *      frees parameter structure in memory
  1174. *
  1175. *****************************************************************************/
  1176.  
  1177. void LIBCALL  Nlm_FreeConfigStruct (void)
  1178.  
  1179. {
  1180.   Nlm_FreeTransientData ();
  1181. }
  1182.  
  1183. #endif /* WIN_MSWIN */
  1184.  
  1185.  
  1186. static Nlm_Boolean Nlm_Qualified( Nlm_CharPtr path )
  1187. {
  1188.   Nlm_Int2 l,k;
  1189.   Nlm_CharPtr  p;
  1190.  
  1191.   l = Nlm_StrLen(path);
  1192.   p = path+l;
  1193.   k = 0;
  1194.   while (k < l && k <= 4) {
  1195.      if (*p-- == '.') return TRUE;
  1196.      k++;
  1197.   }
  1198.   return FALSE;
  1199. }
  1200.  
  1201.  
  1202. /*****************************************************************************
  1203. *
  1204. *   Nlm_FindPath (file, section, type, buf, buflen)
  1205. *      finds paths for types of data from configuration files.
  1206. *      if configuration file is found, tries to read the parameter from it,
  1207. *      then appends a directory delimiter character, if necessary.
  1208. *
  1209. *****************************************************************************/
  1210.  
  1211. Nlm_Boolean LIBCALL Nlm_FindPath (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr buf, Nlm_Int2 buflen)   /* length of path buffer */
  1212.  
  1213. {
  1214.   Nlm_Boolean  rsult;
  1215.  
  1216.   rsult = FALSE;
  1217.   if (buf != NULL && buflen > 0) {
  1218.     *buf = '\0';
  1219.     if (file != NULL && *file != '\0' && section != NULL &&
  1220.         *section != '\0' && type != NULL && *type != '\0') {
  1221.       if (Nlm_GetAppParam (file, section, type, "", buf, buflen - 1)) {
  1222.         if (*buf != '\0') {
  1223.             Nlm_FileBuildPath(buf, NULL, NULL);
  1224.         }
  1225.         rsult = TRUE;
  1226.       }
  1227.     }
  1228.   }
  1229.   return rsult;
  1230. }
  1231.  
  1232. Nlm_Int2 LIBCALL Nlm_GetAppParam (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr dflt, Nlm_CharPtr buf, Nlm_Int2 buflen)
  1233. {
  1234.     return Nlm_WorkGetAppParam(file, section, type, dflt, buf, buflen, TRUE);
  1235. }
  1236.  
  1237. Nlm_Boolean LIBCALL Nlm_TransientSetAppParam (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr value)
  1238.  
  1239. {
  1240.   Nlm_env_filePtr  theFile;
  1241.   Nlm_env_itemPtr  eip;
  1242.   Nlm_env_sectPtr  esp;
  1243.   Nlm_env_itemPtr  nextEip;
  1244.  
  1245.   if (file == NULL || *file == '\0' || section == NULL || *section == '\0')
  1246.     return FALSE;
  1247.  
  1248.   for (theFile = Nlm_transientFileList; theFile != NULL; theFile = theFile->next)
  1249.   {
  1250.     if (StringICmp(theFile->name, file) == 0)
  1251.     {
  1252.       for (esp = theFile->envList; esp != NULL; esp = esp->next)
  1253.       {
  1254.         if (esp->name != NULL && StringICmp(esp->name, section) == 0)
  1255.         {
  1256.           if (type == NULL || type[0] == '\0')
  1257.           {
  1258.             /* free all children */
  1259.             for (eip = esp->children; eip != NULL; eip = nextEip)
  1260.             {
  1261.               nextEip = eip->next;
  1262.               Nlm_MemFree (eip->name);
  1263.               Nlm_MemFree (eip->comment);
  1264.               Nlm_MemFree (eip->value);
  1265.               Nlm_MemFree (eip);
  1266.             }
  1267.             esp->children = NULL;
  1268.             esp->transientOnly = TRUE;
  1269.           } else { /* append this type to the section */
  1270.             eip = (Nlm_env_itemPtr) MemNew(sizeof(*eip));
  1271.             eip->name = StringSave(type);
  1272.             eip->value = StringSave(value);
  1273.             eip->next = esp->children;
  1274.             esp->children = eip;
  1275.           }
  1276.           return TRUE;
  1277.         }
  1278.       }
  1279.       break;
  1280.     }
  1281.   }
  1282.  
  1283.   /* create the file data structure if needed */
  1284.   if (theFile == NULL)
  1285.   {
  1286.     theFile = (Nlm_env_filePtr) MemNew(sizeof(*theFile));
  1287.     theFile->name = StringSave(file);
  1288.     theFile->next = Nlm_transientFileList;
  1289.     Nlm_transientFileList = theFile;
  1290.   }
  1291.  
  1292.   /* create the section and type */
  1293.   esp = (Nlm_env_sectPtr) MemNew(sizeof(*esp));
  1294.   esp->name = StringSave(section);
  1295.   esp->next = theFile->envList;
  1296.   theFile->envList = esp;
  1297.   if (type == NULL || type[0] == '\0')
  1298.   {
  1299.     esp->transientOnly = TRUE;
  1300.   } else { /* create the section */
  1301.     esp->transientOnly = FALSE;
  1302.     eip = (Nlm_env_itemPtr) MemNew(sizeof(*eip));
  1303.     eip->name = StringSave(type);
  1304.     eip->value = StringSave(value);
  1305.     eip->next = NULL;
  1306.     esp->children = eip;
  1307.   }
  1308.  
  1309.   return TRUE;
  1310. }
  1311.  
  1312. /* SetAppParam is writing a value to the real config file, so log this value, if
  1313.    necessary, into the "transient" data structures */
  1314. static void Nlm_TransientLogSetApp (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr value)
  1315.  
  1316. {
  1317.   Nlm_env_filePtr  theFile;
  1318.   Nlm_env_itemPtr  eip;
  1319.   Nlm_env_sectPtr  esp;
  1320.  
  1321.   if (file == NULL || *file == '\0' || section == NULL || *section == '\0')
  1322.     return;
  1323.  
  1324.   if (type == NULL || type[0] == '\0')
  1325.   {
  1326.     for (theFile = Nlm_transientFileList; theFile != NULL; theFile = theFile->next)
  1327.     {
  1328.       if (StringICmp(theFile->name, file) == 0)
  1329.       {
  1330.         for (esp = theFile->envList; esp != NULL; esp = esp->next)
  1331.         {
  1332.           if (esp->name != NULL && StringICmp(esp->name, section) == 0)
  1333.           { /* delete the section by removing section name */
  1334.             esp->name = (Nlm_CharPtr) MemFree(esp->name);
  1335.           }
  1336.         }
  1337.       }
  1338.     }
  1339.   } else {
  1340.     for (theFile = Nlm_transientFileList; theFile != NULL; theFile = theFile->next)
  1341.     {
  1342.       if (StringICmp(theFile->name, file) == 0)
  1343.       {
  1344.         for (esp = theFile->envList; esp != NULL; esp = esp->next)
  1345.         {
  1346.           if (esp->name != NULL && StringICmp(esp->name, section) == 0 &&
  1347.               esp->transientOnly)
  1348.           { /* append this type to the section */
  1349.             eip = (Nlm_env_itemPtr) MemNew(sizeof(*eip));
  1350.             eip->name = StringSave(type);
  1351.             eip->value = StringSave(value);
  1352.             eip->next = esp->children;
  1353.             esp->children = eip;
  1354.           }
  1355.         }
  1356.       }
  1357.     }
  1358.   }
  1359. }
  1360.  
  1361. static Nlm_Boolean Nlm_TransientLookup (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr dflt, Nlm_CharPtr buf, Nlm_Int2 buflen)
  1362.  
  1363. {
  1364.   Nlm_env_filePtr  theFile;
  1365.   Nlm_env_itemPtr  eip;
  1366.   Nlm_env_sectPtr  esp;
  1367.   Nlm_Int2         totlen;
  1368.   Nlm_Int2         bytesToAppend;
  1369.  
  1370.   if (file == NULL || *file == '\0' || section == NULL || *section == '\0')
  1371.     return FALSE;
  1372.  
  1373.   for (theFile = Nlm_transientFileList; theFile != NULL; theFile = theFile->next)
  1374.   {
  1375.     if (StringICmp(theFile->name, file) == 0)
  1376.     {
  1377.       for (esp = theFile->envList; esp != NULL; esp = esp->next)
  1378.       {
  1379.         if (esp->name != NULL && StringICmp(esp->name, section) == 0)
  1380.         {
  1381.           if (type == NULL || type[0] == '\0')
  1382.           { /* concatenate all types (keys) within section */
  1383.             *buf = '\0';
  1384.             totlen = 0;
  1385.             for (eip = esp->children; eip != NULL; eip = eip->next)
  1386.             {
  1387.               bytesToAppend = StrLen(eip->name) + 1;
  1388.               bytesToAppend = MIN(bytesToAppend, buflen - totlen);
  1389.               StrNCpy(&buf[totlen], eip->name, bytesToAppend);
  1390.               totlen += bytesToAppend;
  1391.             }
  1392.             if (totlen > 0 && buf[totlen] == '\0')
  1393.             {
  1394.                 totlen--; /* account for final null character */
  1395.             }
  1396.             /* now append the GetAppParam() data */
  1397.             if (! esp->transientOnly)
  1398.             { /* GetAppParam data can be trusted ... append it to buf */
  1399.               Nlm_WorkGetAppParam(file, section, NULL, "", &buf[totlen],
  1400.                                   buflen - totlen, FALSE);
  1401.             }
  1402.             return TRUE;
  1403.           } else {
  1404.             for (eip = esp->children; eip != NULL; eip = eip->next)
  1405.             {
  1406.               if (StringICmp(eip->name, type) == 0)
  1407.               {
  1408.                 *buf = '\0';
  1409.                 Nlm_StringNCat (buf, eip->value, buflen);
  1410.                 return TRUE;
  1411.               }
  1412.             }
  1413.             if (esp->transientOnly)
  1414.             { /* GetAppParam data cannot be trusted ... use the default */
  1415.               *buf = '\0';
  1416.               if (dflt) Nlm_StringNCat (buf, dflt, buflen);
  1417.               return TRUE;
  1418.             }
  1419.           }
  1420.         }
  1421.       }
  1422.     }
  1423.   }
  1424.  
  1425.   /* not found ... GetAppParam() should search the real config file */
  1426.   return FALSE;
  1427. }
  1428.  
  1429. static void Nlm_FreeEnvData (Nlm_env_sectPtr esp)
  1430.  
  1431. {
  1432.   Nlm_env_itemPtr  eip;
  1433.   Nlm_env_itemPtr  nextEip;
  1434.   Nlm_env_sectPtr  nextEsp;
  1435.  
  1436.   while (esp != NULL) {
  1437.     nextEsp = esp->next;
  1438.     eip = esp->children;
  1439.     while (eip != NULL) {
  1440.       nextEip = eip->next;
  1441.       Nlm_MemFree (eip->name);
  1442.       Nlm_MemFree (eip->comment);
  1443.       Nlm_MemFree (eip->value);
  1444.       Nlm_MemFree (eip);
  1445.       eip = nextEip;
  1446.     }
  1447.     Nlm_MemFree (esp->name);
  1448.     Nlm_MemFree (esp->comment);
  1449.     Nlm_MemFree (esp);
  1450.     esp = nextEsp;
  1451.   }
  1452. }
  1453.  
  1454.  
  1455. static void Nlm_FreeTransientData (void)
  1456. {
  1457.   Nlm_env_filePtr efp, nextEfp;
  1458.  
  1459.   efp = Nlm_transientFileList;
  1460.   while (efp != NULL) {
  1461.     nextEfp = efp->next;
  1462.     Nlm_FreeEnvData (efp->envList);
  1463.     Nlm_MemFree (efp->name);
  1464.     Nlm_MemFree (efp);
  1465.     efp = nextEfp;
  1466.   }
  1467.   Nlm_transientFileList = NULL;
  1468. }
  1469.